package com.snap.vseries.fragment;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.snap.vseries.AppConfig;
import com.snap.vseries.BuildConfig;
import com.snap.vseries.Constants;
import com.snap.vseries.R;
import com.snap.vseries.base.BaseFragment;
import com.snap.vseries.bean.AnalysisProtocol;
import com.snap.vseries.bean.ChannelBean;
import com.snap.vseries.bean.ExpInfo;
import com.snap.vseries.bean.HoleInfo;
import com.snap.vseries.chart.MyMarkerView;
import com.snap.vseries.chart.PLineChart;
import com.snap.vseries.chart.PointLineDataSet;
import com.snap.vseries.listener.IFragmentListener;
import com.snap.vseries.ui.widget.ChannelLayout;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;

@SuppressLint("ValidFragment")
public class ChartAmpFitFragment extends BaseFragment {

    private Bitmap bitmap;
    private IFragmentListener listener;
    private int channelFlag;
    private boolean[] bs;

    @BindView(R.id.chart_layout)
    LinearLayout chartLayout;
    @BindView(R.id.empty_layout)
    FrameLayout emptyLayout;
    @BindView(R.id.ll)
    ChannelLayout ll;
    @BindView(R.id.chart)
    PLineChart chart;

    private ExpInfo experimentInfo;

    private int lastChannelFlag;


    public ChartAmpFitFragment(ExpInfo experimentInfo) {
        this.experimentInfo = experimentInfo;
    }

    @Override
    protected int layoutResId() {
        return R.layout.fragment_chart_amp_fit;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        initViews();
        initData();
        if (experimentInfo.getHoleInfo() == null) {
            return;
        }
        String[] contents = new String[]{experimentInfo.getFamName(), experimentInfo.getVicName(), experimentInfo.getRoxName(), experimentInfo.getCy5Name()};
        ll.initView(contents, experimentInfo.getHoleInfo().getChannelJoinFlag());
    }

    public View getAmpFitView() {
        return chartLayout;
    }


    private void initViews() {
        //图表整体的一些设置
        chart.setDrawGridBackground(false);
        chart.getDescription().setEnabled(false);
        chart.getLegend().setEnabled(false);
        chart.setDrawBorders(false);
        chart.setMaxVisibleValueCount(0);

        //左右的两根Y轴配置
        chart.getAxisRight().setEnabled(false);
        YAxis yAxis = chart.getAxisLeft();
        yAxis.setEnabled(true);
        yAxis.setDrawAxisLine(true);
        yAxis.setDrawGridLines(true);
        yAxis.setGridColor(0xffe8e9ee);
        yAxis.setTextColor(0xff8d909f);
        yAxis.setTextSize(12f);
        yAxis.setGranularity(0.02f);
        yAxis.setLabelCount(10);

        //X轴配置
        XAxis xAxis = chart.getXAxis();
        xAxis.setEnabled(true);
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setDrawAxisLine(true);
        xAxis.setDrawGridLines(true);
        xAxis.setGridColor(0xffe8e9ee);
        xAxis.setTextColor(0xff8d909f);
        xAxis.setTextSize(12f);
        xAxis.setGranularity(1);
        xAxis.setLabelCount(10);

        //操作相关
        chart.getViewPortHandler().setMinMaxScaleX(1f, 5f);
        chart.getViewPortHandler().setMinMaxScaleY(1f, 5f);
        chart.setTouchEnabled(true);
        chart.setDragEnabled(true);
        chart.setScaleEnabled(true);
        chart.setPinchZoom(true);

        chart.setMarker(new MyMarkerView(getContext(), R.layout.custom_marker_view, 1));
        chart.setDrawMarkers(true);

        chart.invalidate();
    }

    private void initData() {
        if (experimentInfo.getHoleInfo().getChannelData() == null) {
            return;
        }
        List<ILineDataSet> dataSets = new ArrayList<>();
        HoleInfo holeInfo = experimentInfo.getHoleInfo();
        for (int i = 0; i < AppConfig.TOTAL_HOLE_COUNT * AppConfig.TOTAL_CHANNEL_COUNT; i++) {
            PointLineDataSet dataSet = new PointLineDataSet(new ArrayList<>(), (i + 1) + "");
            dataSets.add(dataSet);

            ChannelBean bean = experimentInfo.getHoleInfo().getChannelData().get(i);

            int whichChannel = i / AppConfig.TOTAL_HOLE_COUNT;
            boolean enable = (holeInfo.getChannelJoinFlag() >> whichChannel & 0x01) == 0x01;
            if (bean != null && bean.getFit() != null && enable) {
                dataSet.setMode(LineDataSet.Mode.LINEAR);//线的样式
                dataSet.setLineWidth(2f);//线宽
                dataSet.setDrawValues(false);
                dataSet.setDrawCircles(false);
                dataSet.setDrawCircleHole(false);
                dataSet.setCircleRadius(2.5f);
                dataSet.setCircleColor(Constants.CHANNEL_DEFAULT_COLORS[i / AppConfig.TOTAL_HOLE_COUNT % AppConfig.TOTAL_CHANNEL_COUNT]);
                dataSet.setColor(Constants.CHANNEL_DEFAULT_COLORS[i / AppConfig.TOTAL_HOLE_COUNT % AppConfig.TOTAL_CHANNEL_COUNT]);
                Bundle b = new Bundle();
                b.putInt("channelIndex", whichChannel + 1);
                b.putInt("holeIndex", i % AppConfig.TOTAL_HOLE_COUNT + 1);
                for (int j = 0; j < bean.getFit().length; j++) {
                    dataSet.addEntry(new Entry(j + 1, bean.getFit()[j], b));
                }

                if (bean.getCtValue() != 0 && bean.getThreshold() != 0) {
                    dataSet.addPoint(new Entry(bean.getCtValue(), bean.getThreshold(), whichChannel));
                } else {
                    dataSet.addPoint(new Entry(0, 0, whichChannel));
                }

                if (BuildConfig.DEBUG || AppConfig.Dynamic.analysis_debug_mode) {
                    int start = bean.getBlStart();
                    int stop = bean.getBlStop();
                    if (start != 0 && stop != 0) {
                        dataSet.addPoint(new Entry(start, bean.getFit()[start - 1]));
                        dataSet.addPoint(new Entry(stop, bean.getFit()[stop - 1]));
                    }
                }

                if (dataSet.getEntryCount() == 1) {
                    dataSet.setDrawCircles(true);
                } else {
                    dataSet.setDrawCircles(false);
                }
            }
        }

        LineData lineData = new LineData(dataSets);
        chart.setData(lineData);

        resetAxis(lineData.getYMax());

        chart.invalidate();
        if (listener == null) {
            tryShowLines();
        } else {
            setShowLines(bs, channelFlag);
        }
        hasData(chart.getData().getEntryCount() > 0);
    }

    private void resetAxis(float yMax) {
        LineData lineData = chart.getLineData();
        XAxis xAxis = chart.getXAxis();
        YAxis yAxis = chart.getAxisLeft();

        //y:0 - setting.lightBase*2.5
        //然后动态调整 x:10的倍数
        //          y:超过base*2.5   maxValue*1.1
        int xMax = lineData.getMaxEntryCountSet().getEntryCount();
        int xRound = (xMax + 9) / 10 * 10;
        xMax = xRound - xMax > 1 ? xRound : xRound + 2;
        xAxis.setAxisMaximum(xMax);
        xAxis.setAxisMinimum(0);

        float yInit = 1.4f;
        if (yMax <= yInit) {
            yMax = yInit;
        } else {
            yMax *= 1.1f;
        }
        yAxis.setAxisMaximum(yMax);
        yAxis.setAxisMinimum(0.9f);
    }

    private void tryShowLines() {
        if (getParentFragment() == null) {
            return;
        }
        Bundle bundle = ((DetailAnalyzeFragment) getParentFragment()).getChooseInfo();
        if (bundle != null) {
            boolean[] bs = bundle.getBooleanArray("check");
            int channelFlag = bundle.getInt("channelFlag");
            setShowLines(bs, channelFlag);
        }
    }

    public void setShowLines(boolean[] bs, int channelFlag) {
        if (chart == null || bs == null) {
            return;
        }
        chart.post(() -> {
            if (chart == null || chart.getData() == null || experimentInfo == null) {
                return;
            }
            LineData data = chart.getLineData();
            for (int i = 0; i < bs.length; i++) {
                ILineDataSet lineDataSet = data.getDataSetByIndex(i);
                if (lineDataSet != null) {
                    lineDataSet.setVisible(bs[i]);
                    lineDataSet.setHighlightEnabled(bs[i]);
                }
            }
            if (channelFlag != lastChannelFlag) {

                chart.getAxisLeft().removeAllLimitLines();
                List<AnalysisProtocol> protocols = experimentInfo.getProtocols();
                for (int i = 0; i < protocols.size(); i++) {
                    if (protocols.get(i).isAutoThreshold()) continue;
                    if ((channelFlag >> i & 0x01) == 0x01) {
                        LimitLine line = new LimitLine(protocols.get(i).getThreshold());
                        line.enableDashedLine(5, 2, 0);
                        line.setLineWidth(2f);
                        line.setLineColor(Constants.CHANNEL_DEFAULT_COLORS_A50[i]);
                        chart.getAxisLeft().addLimitLine(line);
                    }
                }

                float[] maxArray = new float[AppConfig.TOTAL_CHANNEL_COUNT];
                for (int i = 0; i < bs.length; i++) {
                    int whichChannel = i / AppConfig.TOTAL_HOLE_COUNT;
                    if ((channelFlag >> whichChannel & 0x01) != 0x01) {
                        continue;
                    }
                    ILineDataSet lineDataSet = data.getDataSetByIndex(i);
                    if (lineDataSet != null && lineDataSet.getYMax() > maxArray[whichChannel]) {
                        maxArray[whichChannel] = lineDataSet.getYMax();
                    }
                }
                float maxY = 0f;
                for (int i = 0; i < maxArray.length; i++) {
                    if (maxArray[i] > maxY) {
                        maxY = maxArray[i];
                    }
                }
                resetAxis(maxY);
                lastChannelFlag = channelFlag;
            }
            data.notifyDataChanged();
            chart.notifyDataSetChanged();
            chart.invalidate();
            chartLayout.post(() -> {
                if (listener != null) {
                    listener.onFragmentAttachedToWindow();
                }
            });
        });
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        if (!hidden) {
            if (experimentInfo.getHoleInfo().getChannelData() == null) {
                hasData(false);
            } else {
                hasData(chart.getData().getEntryCount() > 0);
            }
        }
    }

    private void hasData(boolean b) {
        emptyLayout.setVisibility(b ? View.GONE : View.VISIBLE);
        if (getParentFragment() != null) {
            ((DetailAnalyzeFragment) getParentFragment()).setGroupLlVisibility(b ? View.VISIBLE : View.GONE);
        }
    }

    public void setListener(IFragmentListener listener, int channelFlag, boolean[] bs, boolean call) {
        this.listener = listener;
        this.channelFlag = channelFlag;
        this.bs = bs;
        if (call) {
            setShowLines(bs, channelFlag);
        }
    }
}